package net.cyndeline

import net.cyndeline.entitySystem.EntityRef

/**
 * A container for various items (spells, equipment, items).
 */
trait Slots {
  
  /** 
   * @return The total number of slots. 
   */
  def size: Int
  
  /**
   * @param slotType Type of slot to look for. 
   * @return How many slots of a certain type is present. 
   */
  def size(slotType: ItemType): Int
  
  /**
   * @param item Item to check for existence of.
   * @return True if storage contains the specified item.
   */
  def contains(item: EntityRef): Boolean
  
  /** 
   * @param slotType Type of slot to look for.
   * @return How many slots of a certain type that currently doesn't 
   * 				 have items in them. 
   */
  def freeSlots(slotType: ItemType): Int

  
  /**
   * @param item Item who's slot is being requested.
   * @return The slot position of the item request, or None if the item 
   * 				 isn't in the storage. The first position of any slot
   *      			 type is 0.
   */
  def itemPosition(item: EntityRef, slotType: ItemType): Option[Int]
  
  /**
   * @param pos The slot position to retrieve the item for. 0 is the first slot.
   * @return The item currently in the specified slot, or None if the slot
   * 				 is empty. Throws an error if outside slot bounds.
   */
  def item(pos: Int, slotType: ItemType): Option[EntityRef]
  
  /**
   * @return A list of Slot-number/entity tuples, with None for 
   * 				 open positions.
   */
  def items(slotType: ItemType): List[(Int, Option[EntityRef])]
  
  /**
   * Adds an empty slot of a given type.
   * @param slotType What type of slot to add.
   */
  def addSlot(slotType: ItemType)
  
  /**
   * Adds an item entity to a slot.
   * @param item The item entity to add.
   * @param slot Which slot position to add it to. 0 indicates the first slot.
   * @return True if the item was added, false if the slot was full
   * 				 or if the entity couldn't be placed in the slot, or if the item
   *      	 is already present elsewhere. Throws an exception if the slot is 
   *         out of bounds, or if the added entity isn't a spell.
   */
  def addItem(item: EntityRef, slot: Int, slotType: ItemType): Boolean
  
  /**
   * Adds an item to the slot with the lowest available position.
   * @param item Item to add.
   * @return True if the item was added, false if no free slots existed or if
   * 				 the item is already present.
   */
  def addItem(item: EntityRef, slotType: ItemType): Boolean
  
  /**
   * Removes an item from the storage.
   * @param item The item to remove.
   * @return True if the item was removed, false if it didn't exist in storage.
   */
  def removeItem(item: EntityRef): Boolean
  
  /**
   * Moves an item from one slot to another.
   * @param item Item to move.
   * @param newPos Position to move the item to. Must be within the range
   * 			   0 to slot size - 1.
   * @return True if the item was moved, otherwise false.
   */
  def moveItem(item: EntityRef, newPos: Int, toSlotType: ItemType): Boolean
  
  /**
   * Switches place with two items.
   * @param item1 First item to switch.
   * @param item2 Second item to switch.
   * @return True if the items switched place, false if one or both didn't exist.
   */
  def switchItems(item1: EntityRef, item2: EntityRef, item1SlotType: ItemType, item2SlotType: ItemType): Boolean
  
  /**
   * Removes all item.
   */
  def clearItems(slotType: ItemType)
  
  /**
   * Removes all slots and all spells in them.
   */
  def clearSlots()
  
  /**
   * Returns a new slot storage with deep copies of the elements in this one.
   */
  def copy: Slots
}